// Copyright 2010 Alexandre Tristan St-Cyr <tristan.stcyr@gmail.com>

package com.codeplex.loadjava;

import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;



class JavaRepositoryLoader {
	
	private static Logger logger = Logger.getLogger(JavaRepositoryLoader.class.getCanonicalName());
	
	private IJavaRepository repository;
	
	private String classpath;
	
	public JavaRepositoryLoader(IJavaRepository repository, IJavaLoaderSettings settings)
	{
		this.repository = repository;
		this.classpath = settings.getClasspath();
	}
	
	private JavaModelCounterVisitor getEntityCount(String classpath) {
		JavaModelCounterVisitor counterVisitor = new JavaModelCounterVisitor();
		final IJavaModelVisitor bufferedVisitor = new BufferedJavaEntityAdapter(counterVisitor);
		JavaModelReader entityReader = new JavaModelReader(classpath);
		entityReader.accept(bufferedVisitor);
		return counterVisitor;
	}
	
	public boolean load()
	{
		try {
			
			logger.log(Level.INFO, "Counting entities...");
			
			JavaModelCounterVisitor count = getEntityCount(classpath);
			
			logger.log(Level.INFO, "Finished counting.");
			logCount(count);
			logger.log(Level.INFO, "Loading data...");
			
			Long firstClassId = null, firstMethodId = null, firstFieldId = null, firstTypeId = null;
			
			if (count.getClassCount() > 0)
			{
				firstClassId = repository.newIdInterval("Classes", count.getClassCount());
			}
			
			if (count.getMethodCount() > 0)
			{
				firstMethodId = repository.newIdInterval("Methods", count.getMethodCount());
			}
			
			if (count.getTypeCount() > 0)
			{
				firstTypeId = repository.newIdInterval("Types", count.getTypeCount());
			}
			
			if (count.getFieldCount() > 0)
			{
				firstFieldId = repository.newIdInterval("Fields", count.getFieldCount());
			}
			
			final IJavaModelVisitor loaderVisitor = new BufferedJavaEntityAdapter(new JavaModelLoaderVisitor(
					this.repository, firstClassId, firstMethodId,firstTypeId, firstFieldId));
			JavaModelReader entityReader = new JavaModelReader(classpath);
			entityReader.accept(loaderVisitor);
			
			repository.executeBatchInserts();
		}
		catch(SQLException e) {
			logger.log(Level.SEVERE, e.getMessage(), e);
			return false;
		}
		
		return true;
	}
	
	private void logCount(JavaModelCounterVisitor count)
	{
		StringBuilder message = new StringBuilder();
		
		message.append("Counted:\n");
		
		String[] names = {
				"Classes", "ClassDefinitions",
				"Methods", "MethodDefinitions",
				"Fields", "FieldDefinitions",
				"FieldReferences", "InterfaceImplementations",
				"MethodExceptions", "MethodInvocations",
				"MethodParameters", "TypeReferences"
		};
		long[] counts = {
				count.getClassCount(), count.getClassDefinitionCount(),
				count.getMethodCount(), count.getMethodDefinitionCount(),
				count.getFieldCount(), count.getFieldDefinitionCount(),
				count.getFieldReferenceCount(), count.getInterfaceImplementationCount(),
				count.getMethodExceptionCount(), count.getMethodInvocationCount(),
				count.getMethodParameter(), count.getTypeCount()
		};
		
		long total = 0;
		for(int i = 0; i < names.length; i++) {
			message.append("\t");
			message.append(names[i]);
			message.append(": ");
			message.append(counts[i]);
			message.append("\n");
			total += counts[i];
		}
		
		message.append("\tTotal:");
		message.append(total);
		message.append(" rows");
		
		logger.log(Level.INFO, message.toString());
	}
}
